package org.myspringframework.mvc;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.myspringframework.mvc.processor.RequestProcessor;
import org.myspringframework.mvc.render.DefaultResultRender;
import org.myspringframework.mvc.render.InternalErrorResultRender;
import org.myspringframework.mvc.render.ResultRender;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Iterator;
import java.util.Objects;

/**
 * org.myspringframework.mvc <br>
 * 1. 以责任链的模式执行注册的请求处理器. <br>
 * 2. 委派给特定的Render实例对处理后的结果进行渲染. <br>
 *
 * @author jaymin
 * @since 2021/5/22
 */
@Data
@Slf4j
public class RequestProcessorChain {
    /**
     * 请求处理迭代器
     */
    private Iterator<RequestProcessor> requestProcessorIterator;
    /**
     * 请求request
     */
    private HttpServletRequest httpServletRequest;
    /**
     * 请求response
     */
    private HttpServletResponse httpServletResponse;
    /**
     * 请求方法,例如:GET、POST
     */
    private String requestMethod;
    /**
     * 请求路径
     */
    private String requestPath;
    /**
     * http响应请求状态码
     */
    private int responseCode;
    /**
     * 请求结果渲染器
     */
    private ResultRender resultRender;

    /**
     * @param processorIterator 请求处理拦截链
     * @param request           Http请求
     * @param response          Http响应
     */
    public RequestProcessorChain(Iterator<RequestProcessor> processorIterator, HttpServletRequest request, HttpServletResponse response) {
        this.requestProcessorIterator = processorIterator;
        this.httpServletRequest = request;
        this.httpServletResponse = response;
        this.requestMethod = request.getMethod();
        this.requestPath = request.getPathInfo();
        this.responseCode = HttpServletResponse.SC_OK;
    }

    /**
     * 以责任链的模式执行请求链路 <br>
     * 1. 通过迭代器遍历注册的请求处理器实现类列表<br>
     * 2. 直到某个请求处理器执行后返回false为止 <br>
     * 3. 期间如果出现异常，则交由内部异常渲染器处理 <br>
     */
    public void doRequestProcessorChain() {
        while (requestProcessorIterator.hasNext()) {
            RequestProcessor requestProcessor = requestProcessorIterator.next();
            try {
                if (!requestProcessor.proceed(this)) {
                    break;
                }
            } catch (Exception e) {
                this.resultRender = new InternalErrorResultRender(e.getMessage());
                log.error("doRequestProcessorChain error:" + e);
            }
        }
    }

    /**
     * 执行处理器 <br>
     * 1. 如果请求处理器实现类均未选择合适的渲染器，则使用默认的 <br>
     * 2. 调用渲染器的render方法对结果进行渲染
     */
    public void doRender() {
        if (Objects.isNull(this.resultRender)) {
            this.resultRender = new DefaultResultRender();
        }
        try {
            this.resultRender.render(this);
        } catch (Exception e) {
            log.error("doRender error:" + e);
            throw new RuntimeException(e);
        }
    }
}
